﻿namespace Samples.Explorer.Controllers.Explorer
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.Hosting;

    using Samples.Explorer.Controllers.Shared;

    public class DirectoryView
    {
        public string VirtualPath { get; set; }

        public EntrySource Filter { get; set; }

        public IEnumerable<Breadcrumb> Breadcrumbs { get; set; } 

        public IEnumerable<Entry> Entries { get; set; } 

        public static DirectoryView Create(VirtualDirectory virtualDirectory, EntrySource filter, Func<string, string> directoryUrlFor)
        {
            var entries = EntriesFrom(virtualDirectory, directoryUrlFor);

            if(filter != EntrySource.Merged)
            {
                entries = entries.Where(e => e.Source == EntrySource.Merged || e.Source == filter);
            }

            return new DirectoryView
            {
                VirtualPath = virtualDirectory.VirtualPath,
                Filter = filter,
                Breadcrumbs = BreadCrumbsFrom(virtualDirectory.VirtualPath, directoryUrlFor).ToList(),
                Entries = entries.ToList()
            };
        }

        private static IEnumerable<Breadcrumb> BreadCrumbsFrom(string virtualPath, Func<string, string> directoryUrlFor)
        {
            var path = "/";

            yield return new Breadcrumb { Name = "~", Url = directoryUrlFor(path) };

            foreach (var segment in virtualPath.Split('/').Where(s => !string.IsNullOrEmpty(s)))
            {
                path += segment + "/";
                yield return new Breadcrumb { Name = segment, Url = directoryUrlFor(path) };
            }
        }

        private static IEnumerable<Entry> EntriesFrom(VirtualDirectory virtualDirectory, Func<string, string> directoryUrlFor)
        {
            foreach (var directory in virtualDirectory.Directories.Cast<VirtualDirectory>())
            {
                yield return new Entry
                {
                    Name = directory.Name,
                    Url = directoryUrlFor(directory.VirtualPath),
                    VirtualPath = directory.VirtualPath,
                    Source = SourceOf(directory),
                    Type = EntryType.Directory
                };
            }

            foreach (var file in virtualDirectory.Files.Cast<VirtualFile>())
            {
                yield return new Entry
                {
                    Name = file.Name,
                    Url = file.VirtualPath,
                    VirtualPath = file.VirtualPath,
                    Source = SourceOf(file),
                    Type = EntryType.File
                };
            }
        }

        private static EntrySource SourceOf(VirtualDirectory virtualDirectory)
        {
            var typeName = virtualDirectory.GetType().Name;

            return typeName == "MapPathBasedVirtualDirectory"
                ? EntrySource.Application
                : (typeName == "MergedVirtualDirectory"
                       ? EntrySource.Merged
                       : EntrySource.Template);
        }

        private static EntrySource SourceOf(VirtualFile virtualFile)
        {
            return virtualFile.GetType().Name == "MapPathBasedVirtualFile"
                       ? EntrySource.Application
                       : EntrySource.Template;
        }
    }
}